#include <crt_util.h>
#include "test.h"

evloop_t* loop;
evaddr_t addr;
evoper_t* w_oper;
evoper_t* r_oper;
evoper_t* accept_oper;

#define d_buf_len 2

unsigned char* send_data;
unsigned char* recv_data;

int iread = 0;
int iwrite = 0;

_cond_t w_cond;
_mutex_t w_mutex;

_cond_t r_cond;
_mutex_t r_mutex;

void thread_proc1(void* ctx)
{
    sleep_time(3);
    test_conn_oper(loop);
    while (1) {
        sleep_time(1000);
    }
}
void thread_proc2(void* ctx)
{
    _cond_wait(&r_cond);
    test_read_oper(loop);
    while (1) {
        sleep_time(10);
    }
}

void thread_proc3(void* ctx)
{
    _cond_wait(&w_cond);
    sleep_time(10);
    test_write_oper(loop);
    while (1) {
        sleep_time(15);
    }
}

void thread_proc4(void* ctx)
{
    sleep_time(30);
    iwrite = 0;
    iread = 0;
    s_memset(recv_data, 0x00, 4096);
    evoper_read_buf(r_oper, (buf_ptr)recv_data, d_buf_len);
    evloop_enable_read(loop, r_oper, op_ev_level, 0, NULL);
    test_write_oper(loop);
    while (1) {
        sleep_time(15);
    }
}

void test_init_evaddr()
{
    _cond_init(&r_cond);
    _cond_init(&w_cond);

    evloop_alloc(&loop, NULL, loop_alloc);
    evloop_init(loop, 1024, 0);
    evloop_bind_memory(loop, loop_mem_alloc, loop_mem_free, NULL);

    const char* ip = "127.0.0.1";
    addr.ptr = ip;
    addr.len = s_strlen("127.0.0.1");
    _pid_t aa = get_processid();
    aa += 1000;
    addr.port = aa % SHRT_MAX;

    logi("port:%u\n", addr.port);

    send_data = heap_malloc(4096);
    recv_data = heap_malloc(4096);

    s_memset(send_data, 0x00, 4096);
    s_memset(recv_data, 0x00, 4096);

    evoper_alloc(&w_oper, NULL, oper_alloc);
    evoper_alloc(&accept_oper, NULL, oper_alloc);

    test_accept_oper(loop);
}

void test_oper_run()
{
    int rc = S_SUCCESS;
    rc = evloop_run(loop, 5000000);
}

int evop_proc(evevent res, evoper_t* oper, evoper_t* oper_s, evevent event)
{
    if (event == op_ev_connect && res == op_ev_success) {
        logi("open_connect");
        _cond_broadcast(&w_cond);
    } else if (event == op_ev_accept && res == op_ev_success) {
        logi("accept_connect");
        r_oper = oper_s;
        _cond_broadcast(&r_cond);
    } else if (event == op_ev_close && res == op_ev_success) {
        logi("close_connect");
    } else if (event == op_ev_write && res == op_ev_success) {

        buf_len len = evoper_wbyte(oper);

        iwrite = iwrite + d_buf_len;

        evoper_write_buf(oper, send_data + iwrite, d_buf_len);
        if (iwrite == 10)
            evloop_disable_write(loop, oper);

    } else if (event == op_ev_read && res == op_ev_success) {

        buf_len len = evoper_rbyte(oper);
        iread = iread + d_buf_len;
        logi("read string:%s = %d\n", recv_data, iread);
        evoper_read_buf(oper, (buf_ptr)recv_data + iread, d_buf_len);
        if (iread == 10)
            evloop_disable_read(loop, oper);
    }
    return S_SUCCESS;
}

void bind_loop(evloop_t* loop, evoper_t* oper_oper)
{
    evloop_alloc_evoper(loop, oper_oper);
    evoper_bind_handler(oper_oper, evop_proc);
}

void test_accept_oper(evloop_t* loop)
{
    int rc;

    rc = evoper_pollsock(accept_oper, &addr, 1);
    if (rc != S_SUCCESS) {
        logi("evoper_pollsock error");
        return;
    }
    bind_loop(loop, accept_oper);
    evloop_poll(accept_oper, 1);
}

void test_conn_oper(evloop_t* loop)
{
    evoper_sock(w_oper);
    bind_loop(loop, w_oper);
    int rc = evloop_add_connect(w_oper, &addr, NULL);
}

void test_write_oper(evloop_t* loop)
{
    int rc = 0;
    s_strncpy(send_data, "hello,world", 11);

    rc = evoper_write_buf(w_oper, (buf_ptr)send_data, d_buf_len);
    if (rc != S_SUCCESS) {
        logi("evoper_write");
    }

    rc = evloop_enable_write(loop, w_oper, op_ev_level, 0, NULL);

    if (rc != S_SUCCESS) {
        if (rc == S_COMPLETED) {
        } else if (rc != S_PENDING) {
            logi("evloop_add_write");
        }
    }
}
void test_read_oper(evloop_t* loop)
{
    int rc = 0;
    rc = evoper_read_buf(r_oper, (buf_ptr)recv_data, d_buf_len);
    if (rc != S_SUCCESS) {
        logi("evoper_read");
    }

    rc = evoper_bind_handler(r_oper, evop_proc);
    if (rc != S_SUCCESS) {
        logi("evoper_bind_handler");
    }

    rc = evloop_enable_read(loop, r_oper, op_ev_level, d_buf_len, NULL);

    if (rc != S_SUCCESS) {
        if (rc == S_COMPLETED) {
        } else if (rc != S_PENDING) {
            logi("evloop_add_read");
        }
    }
}
